<?php
class IDGenterException extends Exception{}
class idmakersvc
{

    private $_objName;
    public static function getInstance()
    {
        static $ins;
        if (false == $ins instanceof self)
        {
            $ins = new self();
        }
        return $ins;
    }


    public function createid($objName='default')
    {/*{{{*/
        $this->init($objName);
        $lockIns = LockUtil::factory(LockUtil::LOCK_TYPE_DB, array());
        $lockIns->getLock($objName);
        try
        {
            $idset = $this->readIDSet();
            $idset = $this->getBatchID($idset);
        }
        catch (IDGenterException $e)
        {
            $lockIns->releaseLock($objName);
            throw $e;
        }
        $lockIns->releaseLock($objName);
        return $idset['default']['curID'];
    }/*}}}*/

    private function init($objName)
    {/*{{{*/
        $this->_objName = $objName;
        $this->_executer = matrix::get('dbexecuter');
        if (false == $this->_executer instanceof dbexecuter)
            throw new IDGenterException('not an instanceof dbexecuter');
    }/*}}}*/

    private function readIDSet()
    {/*{{{*/
        $cmd = "select sql_no_cache * from idmaker where obj = '$this->_objName';";
        $rows = $this->_executer->query($cmd);
        if (empty($rows))
            throw new Exception('no such objName['.$this->_objName.']');

        $row = $rows[0];
        $idsets = array();
        $idsets[$row['obj']]['curID'] = $row['id'];
        $idsets[$row['obj']]['maxID'] = $row['id'];
        $idsets[$row['obj']]['step'] = $row['step'];
        return $idsets;
    }/*}}}*/

    private function getBatchID($idset)
    {/*{{{*/
        $step = $idset[$this->_objName]['step'];
        $cmd = "update idmaker set id = LAST_INSERT_ID(id + $step) where obj= '$this->_objName';";
        if ($this->_executer->execute($cmd))
        {
            $lastId = $this->_executer->getLastInsertId();
            if (0 < $lastId)
            {
                $idset[$this->_objName]['step'] = $step;
                $idset[$this->_objName]['maxID'] = $lastId;
                $idset[$this->_objName]['curID'] = $lastId - $step;
                return $idset;
            }
        }
        throw new Exception('getBatchID fail!');
    }/*}}}*/
}
